const path = require("path");
const fs = require("fs");
const jwt = require("jsonwebtoken");
const axios = require("axios");
const crypto = require("crypto");
const { v4 } = require("uuid");
const AppConfig = require("$config/app.config");
const WXConfig = require("$config/wx.config");
const { Result } = require("@/libs/result");
const { authModel } = require("./auth.model");
const keyPath = path.join("./app/src/secret-key", "jwt.key");
const secretKey = fs.readFileSync(keyPath, "utf8");
const redisClient = require("@/redis/redis-client");
const RedisKeysConstant = require("@/constants/redis-keys.constant");
const AesSecurity = require("@/security/aes.security");
const fileBusinessService = require("../../common/file-business.service");
const userService = require("../user/user.service");
const { UserCacheTypeEnum } = require("@/common/enums/user.enum");

/**
 * 生成用户token
 * @param {*} param0
 * @returns
 */
async function generateUserToken({ username, id }) {
	return new Promise(resolve => {
		const jwtPayload = {
			username: username,
            n: Date.now(),
            sub: id,
			iat: Math.floor(Date.now() / 1000), // 令牌签发时间
			exp: Math.floor(Date.now() / 1000) + AppConfig.TOKEN_EXPIRED_TIME // 令牌过期时间，10小时
		};
		jwt.sign(jwtPayload, secretKey, { algorithm: "HS256" }, (err, token) => {
			if (err) {
				return resolve(null);
			}
			return resolve(token);
		});
	});
}

/**
 * 生成微信用户token
 * @param {*} param0
 * @returns
 */
async function generateWxUserToken({ openid, session_key }) {
	return new Promise(resolve => {
		const jwtPayload = {
			openid,
			session_key,
            n: Date.now(),
			sub: openid,
			iat: Math.floor(Date.now() / 1000), // 令牌签发时间
			exp: Math.floor(Date.now() / 1000) + AppConfig.TOKEN_EXPIRED_TIME // 令牌过期时间，10小时
		};
		jwt.sign(jwtPayload, secretKey, { algorithm: "HS256" }, (err, token) => {
			if (err) {
				return resolve(null);
			}
			return resolve(token);
		});
	});
}

/**
 * 认证服务
 */
class AuthService {
	userService = userService;
	aesSecurity = new AesSecurity();
	async login({ userName, password }) {
		try {
			const { code, results } = await authModel.login({ userName: userName, password: password });
			if (code !== 200) {
				return Result.Failed("登录失败");
			}
			if (results && results.length === 0) {
				return Result.Failed("登录失败，用户名或密码有误");
			}
			// 根据用户信息生成token
			const userResult = await authModel.getUserInfoById(results[0].id);
			const findUser = userResult.results[0];
			// 生成token
            const token = await generateUserToken({
                username: findUser.name,
                id: findUser.id
            });
            const tokenKey = token.slice(-20).toUpperCase();
			// 存储在redis中
			await redisClient.set(RedisKeysConstant.userAuthInfo(tokenKey), {
				token: token,
				uid: findUser.id,
				session_key: "",
				type: UserCacheTypeEnum.SystemManage
			});
			const result = {
				...findUser,
				access_token: token
			};
			return Result.Success(result);
        } catch (error) {
            console.log('登录失败：', error);
			return Result.Failed('登录失败');
		}
	}

	/**
	 * 微信登录
	 * @param {*} param0
	 * @returns
	 */
	async wechatLogin({ appcode }) {
		try {
			const { status, data } = await axios.get(WXConfig.AUTH_URL, {
				params: {
					appid: WXConfig.APPID,
					secret: WXConfig.SECRET,
					js_code: appcode,
					grant_type: "authorization_code"
				}
			});
			if (status === 200 && data && data.openid) {
				const encryptedOpenid = this.aesSecurity.encrypt(data.openid); // 将openid加密
				// 生成token
				const token = await generateWxUserToken({
					openid: encryptedOpenid,
					session_key: data.session_key
				});
				const findUser = await authModel.getUserInfoByOpenid(encryptedOpenid);
				let user = null;

				// 如果用户未注册
				if (findUser.code === 200 && findUser.results.length === 0) {
					const newUser = await this.createWxUser(encryptedOpenid);
					if (newUser === null) {
						return Result.Failed("登录失败!");
					}
					user = newUser;
                    await userService.createUserDefaultFamilyGroup(newUser.id); // 创建用户默认家庭组
				} else {
					user = findUser.results[0];
				}

				const tokenKey = token.slice(-20).toUpperCase();
				// 存储在redis中
				await redisClient.set(RedisKeysConstant.userAuthInfo(tokenKey), {
					token: token,
					code: appcode,
					uid: user.id,
					openid: encryptedOpenid,
                    session_key: data.session_key,
                    type: UserCacheTypeEnum.WeChat
				});
				return Result.Success({
					token: token
				});
			}
			return Result.Failed("wechart authentication failure!", undefined, data);
		} catch (error) {
			console.log(error);
			return Result.Failed(error);
		}
	}

	/**
	 * 验证登录状态
	 * @param {*} param0
	 */
	async checkAuthState({ gid, user }) {
		try {
			const result = await authModel.getUser(user.uid);
			if (result.code === 200) {
				const findUser = result.results[0];
                if (findUser && findUser.status !== 0) {
                    return Result.Failed('账户已锁定或禁用');
                }
				return Result.Success(true);
			}
		} catch (error) {
			return Result.Failed(error);
		}
	}

	/**
	 * 账户注册
	 * @param {*} param0
	 */
	async userRegister({ name, password }) {
		try {
			if (!name || !password) {
				return Result.Failed("参数有误");
			}
			const checkResult = await authModel.checkUserNameExist(name);
			if (checkResult.code === 200 && checkResult.results.length > 0) {
				return Result.Failed("用户已存在");
			}
			const id = v4();
			const result = await authModel.createPcUser({
				id: id,
				name: name,
				password: password,
				phone: "",
				nick_name: name,
				real_name: "",
				wx_openid: "",
				avatar_image: "",
				type: 0,
				create_user: "admin"
			});
			if (result.code === 200) {
				const findUser = await authModel.getUserInfoById(id);
				return Result.Success(findUser.results[0]);
			}
			return Result.Failed("用户查询失败");
		} catch (error) {
			return Result.Failed(error);
		}
	}

	/**
	 * 获取登录信息
	 * @param {*} param0
	 */
	async getUserProfile({ user }) {
		try {
            let userResult = null;
            // 管理后台用户
            if (user.type === UserCacheTypeEnum.SystemManage) {
                const idResult = await authModel.getUserInfoById(user.uid);
                if (idResult.code === 200 && idResult.results.length > 0) {
                    userResult = idResult.results[0];
                }
            }
            // 微信用户
            if (user.type === UserCacheTypeEnum.WeChat) {
                const openidResult = await authModel.getUserInfoByOpenid(user?.openid);
                if (openidResult.code === 200 && openidResult.results.length > 0) {
                    userResult = openidResult.results[0];
                }
            }
			if (userResult !== null) {
				const files = await fileBusinessService.getBusinessFiles(userResult.avatar_image); // 查询头像
				const resultFiles = await fileBusinessService.setFilesPreviewPath({ files }); // 设置预览地址
				userResult.avatar = resultFiles[0]?.previewPath || null;
				return Result.Success(userResult);
			}
			return Result.Failed("用户查询失败");
        } catch (error) {
            console.log('获取用户登录信息失败：', error);
			return Result.Failed(error);
		}
	}

	async getWxUserProfileData(encryptedData, iv, sessionKey) {}

	/**
	 * 解密微信信息
	 * @param {*} encryptedData
	 * @param {*} iv
	 * @param {*} sessionKey
	 */
	decryptWxData(encryptedData, iv, sessionKey) {
		try {
			// 将 Base64 编码的字符串解码为 Buffer
			const encryptedDataBuffer = Buffer.from(encryptedData, "base64");
			const ivBuffer = Buffer.from(iv, "base64");
			const sessionKeyBuffer = Buffer.from(sessionKey, "base64");

			// 创建解密器
			const decipher = crypto.createDecipheriv("aes-128-cbc", sessionKeyBuffer, ivBuffer);
			decipher.setAutoPadding(true);

			// 解密数据
			let decoded = decipher.update(encryptedDataBuffer, "binary", "utf8");
			decoded += decipher.final("utf8");

			// 返回解密后的 JSON 对象
			return JSON.parse(decoded);
		} catch (error) {
			console.error("解密失败:", error);
			throw new Error("Failed to decrypt user info");
		}
	}

	/**
	 * 创建微信用户
	 * @param {*} param0
	 */
	async createWxUser(openid) {
		try {
			const id = v4();
			const name = "微信用户";
			const createResult = await authModel.createWxUser({
				id: id,
				name: "",
				phone: "",
				nick_name: name,
				real_name: "",
				wx_openid: openid,
				avatar_image: "",
				type: 1,
				create_user: "admin"
			});
			if (createResult.code === 200 && createResult.results.affectedRows > 0) {
				const findUser = await authModel.getUserInfoByOpenid(openid);
				return findUser.results[0];
			}
			return null;
		} catch (error) {
			console.log(error);
			return null;
		}
	}
	/**
	 * 设置用户隐私协议
	 * @param {*} param0
	 */
	async setPrivacyAgreement({ user }) {
		try {
            const result = await authModel.setUserPrivacyAgreement(user.uid);
            if (result.code === 200 && result.results.changedRows > 0) {
                return Result.Success();
            }
            return Result.Failed('设置隐私协议失败');
		} catch (error) {
			console.log(error);
			return Result.Failed(error);
		}
	}
}

module.exports = {
	authService: new AuthService()
};
